package org.spiderflow.core.job;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spiderflow.context.SpiderContext;
import org.spiderflow.context.SpiderContextHolder;
import org.spiderflow.core.Spider;
import org.spiderflow.core.model.SpiderFlow;
import org.spiderflow.core.model.Task;
import org.spiderflow.core.service.SpiderFlowService;
import org.spiderflow.core.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 爬虫定时执行
 *
 * @author Administrator
 */
@Component
public class SpiderJob extends QuartzJobBean {

    @Autowired
    private Spider spider;

    @Autowired
    private SpiderFlowService spiderFlowService;

    @Autowired
    private TaskService taskService;

    private static Map<Integer, SpiderContext> contextMap = new HashMap<>();

    @Value("${spider.job.enable:true}")
    private boolean spiderJobEnable;

    @Value("${spider.workspace}")
    private String workspace;

    private static Logger logger = LoggerFactory.getLogger(SpiderJob.class);

    @Override
    protected void executeInternal(JobExecutionContext context) {
        if (!spiderJobEnable) {
            return;
        }
        JobDataMap dataMap = context.getMergedJobDataMap();
        SpiderFlow spiderFlow = (SpiderFlow) dataMap.get(SpiderJobManager.JOB_PARAM_NAME);
        if ("1".equalsIgnoreCase(spiderFlow.getEnabled())) {
            run(spiderFlow, context.getNextFireTime());
        }
    }

    public void run(String id) {
        run(spiderFlowService.getById(id), null);
    }

    public void run(SpiderFlow spiderFlow, Date nextExecuteTime) {
        Task task = new Task();
        task.setFlowId(spiderFlow.getId());
        task.setBeginTime(new Date());
        taskService.save(task);
        run(spiderFlow, task, nextExecuteTime);
    }

    public void run(SpiderFlow spiderFlow, Task task, Date nextExecuteTime) {
        SpiderJobContext context = null;
        Date now = new Date();
        try {
            context = SpiderJobContext.create(this.workspace, spiderFlow.getId(), task.getId(), false);
            SpiderContextHolder.set(context);
            contextMap.put(task.getId(), context);
            logger.info("开始执行任务{}", spiderFlow.getName());
            spider.run(spiderFlow, context);
            logger.info("执行任务{}完毕，下次执行时间：{}", spiderFlow.getName(), nextExecuteTime == null ? null : DateFormatUtils.format(nextExecuteTime, "yyyy-MM-dd HH:mm:ss"));
        } catch (Exception e) {
            logger.error("执行任务{}出错", spiderFlow.getName(), e);
        } finally {
            if (context != null) {
                context.close();
            }
            task.setEndTime(new Date());
            taskService.saveOrUpdate(task);
            contextMap.remove(task.getId());
            SpiderContextHolder.remove();
        }
        spiderFlowService.executeCountIncrement(spiderFlow.getId(), now, nextExecuteTime);
    }

    public static SpiderContext getSpiderContext(Integer taskId) {
        return contextMap.get(taskId);
    }
}
